package edu.hawaii.teams.halealohacli.command;

import java.util.ArrayList;
import java.util.List;

/**
 * A utility class containing methods that multiple classes may use in the Command package.
 * 
 * @author Branden Ogata
 * 
 */
public class Utility {
  /**
   * Parses a String that is presumed to be a date, returning the year, month, or day.
   * 
   * @param input The String that should contain a date.
   * @param measure The String indicating whether to return the year, month, or day. Valid inputs
   * are "year", "month", and "day" and any other values are rejected. For future development, may
   * want to consider making this an enum; for the time being, it is a bit much work for something
   * so simple.
   * @return value The year, month, or day given in input, as an int.
   * 
   */
  protected static int getDate(String input, String measure) {
    int value = 0;

    // Gets the year, month, or day as appropriate.
    // This is where an enum might be better, since this could be a switch-case statement
    if ("year".equals(measure)) {
      value = Integer.valueOf(input.substring(0, input.indexOf('-')));
    }
    else if ("month".equals(measure)) {
      value = Integer.valueOf(input.substring(input.indexOf('-') + 1, input.lastIndexOf('-')));
    }
    else if ("day".equals(measure)) {
      value = Integer.valueOf(input.substring(input.lastIndexOf('-') + 1));
    }
    return value;
  }

  /**
   * Uses merge sort to sort the Source instances by energy consumption. This could probably use
   * generic types, but that would add an additional step of having to check objects for their type
   * and so forth.
   * 
   * @param list The List of Source instances to sort.
   * @return result The sorted List of Source instances.
   * @throws Exception If problems occur for any reason; a try-catch statement may be better.
   * 
   */
  public static List<String> sortByEnergy(List<String> list) throws Exception {
    List<String> result;

    // If the length of the parameter is 0 or 1, then return the parameter
    if (list.size() <= 1) {
      result = list;
    }
    // Else continue
    else {
      List<String> left = new ArrayList<String>();
      List<String> right = new ArrayList<String>();
      int median = list.size() / 2;

      // Divides into left and right halves
      for (int i = 0; i < median; i++) {
        left.add(list.get(i));
      }
      for (int j = median; j < list.size(); j++) {
        right.add(list.get(j));
      }

      // Merge sort left
      left = sortByEnergy(left);

      // Merge sort right
      right = sortByEnergy(right);

      // Merge the left and right lists together
      result = mergeLists(left, right);
    }
    return result;
  }

  /**
   * Merges two lists for the merge sort.
   * 
   * @param first The first list to merge.
   * @param second The second list to merge.
   * @return result The merged, sorted list.
   * @throws Exception If problems occur for any reason; a try-catch statement may be better.
   * 
   */
  public static List<String> mergeLists(List<String> first, List<String> second) throws Exception {
    List<String> result = new ArrayList<String>();

    // While there are still elements in either of the lists
    while ((!first.isEmpty()) || (!second.isEmpty())) {
      // If only first has elements, then add from first
      if (second.isEmpty()) {
        result.add(first.get(0));
        first.remove(0);
      }

      // If only second has elements, then add from second
      else if (first.isEmpty()) {
        result.add(second.get(0));
        second.remove(0);
      }

      // If both lists have elements, add the smaller one first
      else if ((!first.isEmpty()) && (!second.isEmpty())) {
        double firstValue =
            Double.valueOf(first.get(0).substring(first.get(0).lastIndexOf(" ") + 1));
        double secondValue =
            Double.valueOf(second.get(0).substring(second.get(0).lastIndexOf(" ") + 1));
        if (firstValue <= secondValue) {
          result.add(first.get(0));
          first.remove(0);
        }
        else {
          result.add(second.get(0));
          second.remove(0);
        }
      }
    }
    return result;
  }
}